Как сделать Flash XML слайдшоу на ActionScript 3.0
В этой статье мы покажем вам как сделать Flash XML слайдшоу на ActionScript 3.0. Все изображения и описания, содержащиеся в слайдшоу, будут контролироваться через XML файл, так что вы сможете обновлять и изменять их не трогая исходный FLA файл. Концепция нашего слайдшоу проста, наш SWF файл будет закачивать XML файл в котором есть текстовые описания к каждому закачиваемому изображению. SWF файл затем закачает все эти изображения за один раз и начнет показ когда все изображения будут усспешно закачаны. В самом SWF файле нет ничего кроме ActionScript так как изображения и описания к ним хранятся во вне этого файла. Наша статья разделена на следующие части: 1. Подготовка внешних составляющих и FLA файла.
Подготовка внешних составляющих и FLA файлаПрежде чем начать работать с FLA файлом нам необходимо подготовит все внешние составляющие. Смысл закачивания всего динамически в том, чтобы сделать возможным обновлять наш контент без необходимости изменять исходный FLA файл и снова компелировать SWF каждый раз, когда мы захотим сменить изображения. Вы можете использовать свои собственные изображения если хотите. Начнем с создания папки проекта нашего слайдшоу. Внутри этой папки нужно создать папку для изображений и назвать ее images. Рядом с этой папкой будет создан наш XML файл. XML файл представляет из себя обычный текстовый файл, содержащий в себе специально структуированный код. Откроем Блокнот (или другой простой текстовый редактор, подходящий для программирования, например Notepad++) и сохраним пустой файл как slideshow.xml. Теперь у вас должны быть папка, называющаяся images и xml файл, оба размещенные внутри вашей папки проекта. Подготавливаем XML файлМы собираемся наполнить наш XML файл информацией, необходимой для нашего слайдшоу. В нем будет содержаться два вида информации: Общая структура нашего XML файла приведена в коде, показанном ниже, Один тэг <slideshow> будет содержать в себе несколько тэгов <image />. CODE: <?xml version="1.0" encoding="utf-8"?> Наш код будет содержать следующие параметры, определенные в элементе <slideshow>: 1. Скорость смены изображений в слайдшоу (количество секунд для каждого изображения) Каждый элемент <image /> будет содержать следующие параметры: 1. image URL Значения этих параметров будут использованы Flash при помощи .attrbute свойства XML элемента. Значения этих параметров оределены в коде, находящемся ниже, вы можете скопировать и вставить его в ваш XML файл. Вы можете изменить эти параметры в последствии, когда будете конфигурировать свое собственное слайдшоу. CODE: <?xml version="1.0" encoding="utf-8"?> Вы могли заметить что мы не определили количество изображений в нашем слайдшоу, это потому что ActionScript XML класс может определять количество дочерних нодов внутри элемента и в нашем случае это количество элементов <image /> внутри нашего элемента <slideshow>, тоесть количество изображений в нашем слайдшоу. Подготовка FLA файлаТеперь, когда внешние составляющие нашего слайдшоу готовы, настало время создать FLA файл. Создайте новый файл во Flash в формате AS3. Сохраните его в той же папке, где находятся ваши XML файл и папка с изображениями. Установите разры вашего FLA файла в 500х500 пикселей и частоту кадров в 30 fps. Для того чтобы наше слайдшоу работало, мы должны загрузить и обработать наш XML файл, затем поместить все, необходимые нам данные в легко доступные переменные. Загрузка данных потребует использования такого класса как URLLoader Class и обработка XML файла потребует использование класса XML Class. Создаем необходимые переменные.Теперь мы должны извлечь данные из нашего XML файла и поместить их для исползования в слайдшоу. Перед тем как попытаться загрузить наши данные нам нужно создать переменные которые будут помещать в себе эти данные. Данные, которые мы будем извлекать из XML это: Нам необходимо чтобы переменные оставались доступными в течении всего времени работы нашего клипа, так что нам нужно объявить их явно вне любых функций и циклов. Вы можете это сделать написав следующий код в панели Actions (Действия, если у вас русифицированная версия программы): CODE:
Мы обновим содержание этих переменных после того как загрузим и оьработаем наш XML файл. Загружаем XML файл, используя URLLoader Class.Чтобы закачать любой текстовый контент, такой как XML или HTML во Flash используется класс URLLoader Class. Начнем с создания экземпляра этого класса и затем используем метод .load() чтобы загрузить файл slideshow.xml: CODE:
Этот код должен загрузить наш XML файл во Flash, но но сам по себе не будет ничего делать, так как Flash все еще не сказано, что делать когда файл загрузится. Чтобы произвести действие, когда файл загружен нам нужно использовать обработчик событий Event.COMPLETE. Мы обработаем это событие при помощи функции processXML(), которую создадим позже. Просто добавте следующий код, чтобы использовать метод .addEventListener() для обработки этого события. CODE:
Использование слушателя событий позволит нам произвести действие, когда файл полностью загрузится. Действие - это конечно же обработка данных XML. Обработка данных XML.Мы собираемся обрабатывать наш XML по средствам функции processXML(), которая запускается когда XML файл заканчивает загружаться. Код, который будет запускаться должен распологаться внутри этой функции. Просто напишите это под кодом, который у нас уже есть: CODE:
Обработка данных нашего XML потребует создания экземпляра класса XML Class и присвоения ему данных нашего XML файла. Сделаем это, распологая код внизу внутри функции processXML(): CODE:
Вы должны запомнить что использование ключевого слова var внутри функции делает эту переменную локальной и временной. Это значит что она будет уничтожена когда функция прекратит выполняться. Мы должны использовать этот способ потому что нам не нужна ссылка на данные XML позже, но мы нуждаемся только в некоторых из их. Это потому что мы создали другие переменные раньше, так что теперь можем использовать их для хранения необходимых данных на протяжении всего клипа. Теперь мы можем использовать различные методы класса XML Class для извлечения нужных нам данных. Мы будем использовать оператор @ для извлечения нужного нам значения атрибута. Ссылкe на все элементы image мы создадим сохраняя ссылки к нодам image в XML файле, тогда как общее число изображений будет извлекаться, используя метод .length() на XML список изображений (my_images): CODE:
Теперь, когда данные XML у нас готовы мы будем загружать все наши изображения, используя класс Loader Class. Несколько экземпляров этого класса мы создадим, используя цикл и затем поместим в массив, для легкого доступа в дальнейшем. Мы поместим весь необходимый для этого код в одну функцию, которую назовем loadImages(). Создание функции loadImages()Для того, чтобы сохранять наш код организованным и легко обновляемым, мы собираемся поместить код, необходимый для данного процесса внутри отдельной функции. Мы собираемся назвать эту функцию loadImages(). Напишите следующий код ниже ранее написанного вами кода: CODE:
Создаем циклНам нужен цикл для нашего слайдшоу, так как нам нужно многократное исполнение одних и тех же команд для каждого изображения. Повторяемый код включает в себя: 1. Получение URL изображения из нашего XML списка изображений. Начнем с создания цикла. Наш цикл будет работать до тех пор, пока счетчик i не достигнет общего числа наших изображений: CODE:
Теперь получим URL изображения и сохраним его в локальной переменной my_url. Эта переменная используется только внутри цикла так что нет нужды в глобальной переменной. Переменная i используется для прохода по элементам XML файла и получения действительных URL, и при помощи оператора @ извлечения значения атрибута: CODE:
Теперь создадим временный экземпляр класса Loader Class, используя ключевое слово new, и затем загрузим миниатюру изображения используя метод .load(). Это очень просто: CODE:
Теперь нам нужно использовать слушатель событий. CODE:
Добавим теперь каждый экземпляр загрузчика в массив. Нам нужно сделать это чтобы иметь возможность взаимодействовать с каждым экземпляром загрузчика на протяжении слайдшоу. Конечно, перед тем как мы будем добавлять что-то в массив, нам нужно создать сам массив. Вернемся вверх нашего кода и добавим новый массив с названием my_loader_array, мы объявляем этот массив глобально потому что он понадобится нам и далее в проекте, а не только внутри цикла. CODE:
Теперь мы можем вернуться назад к нашему циклу и использовать метод .push() для вставки каждого нового загрузчика в массив: CODE:
Ну вот. Теперь, когда этот цикл будет вызван, он будет обходить XML файл, извлекать URL, направлять его экземпляру класса Loader Class и затем вставлять этот экземпляр в массив. Конечно, мы еще не определили, что будет происходить, когда каждый экземпляр загрузчика закончит загружать файл. Давайте теперь этим и займемся. Создание функции слушателя событий (Event Listener) .onCompleteМы начнем с определения функции слушателя (listener) .onComplete(). Мы уже зарегистрировали эту функцию внутри цикла. Для этого напишите в самом низу нашего с вами кода следущее: CODE:
Теперь мы просто попросим слушатель событий обновлять счетчик, чтобы проследить сколько изображений уже успешно закачалось. Нам нужно создать этот счетчик в самом верху нашего кода: CODE:
Теперь наша функция .onComplete() может просто добавить 1 к значению этого счетчика, используя оператор ++: CODE:
Это означает, что как только каждое изображение зачивается, значение счетчика my_success_counter будет увеличиваться, чтобы показать общее число изображений, которые закончили закачиваться. Для того чтобы начать наше слайдшоу когда все изображения закончат закачиваться, мы должны сравнить это значение с общим числом изображений в слайдшоу, используя сравнение и только затем начать слайдшоу. CODE:
Наше сравнение запустит функцию startShow(), которая начнет наше слайдшоу: CODE:
Определим значение этой функции в самом низу нашего кода: CODE:
Наша функция loadImages() и поддерживающий её работу слушатель событий теперь готовы. Конечно, для того, чтобы запустить их, мы должны вызвать их из функции processXML(), когда данные XML будут готовы: CODE:
Создание контейнеровПервый шаг в отображении наших изображений потребует создания необходимого количества контейнеров, в которых будет помещаться наш контент. Это необходимый шаг для того, чтобы легко управляться с нашим слайдшоу. Нам необходим основной контейнер, внутри которого мы будет отдельный контейнер для изображений и другой для текстовых описаний, который мы добавим позже. Эти контейнеры должны работать постоянно, поэтому мы должны определить их вне каких либо функций. Напишите в верхней части нашего кода следующее: CODE:
Тезерь вернемся к нашей функции startShow(), используем метод addChild() чтобы добавить эти контейнеры в дисплей лист:
Наши изображения будут помещены внутрь контейнера my_image_slides. Теперь мы собираемся добавить первое изображение в этот контейнер. Создание функции nextImage()Функция nextImage() будет извлекать нужное изображение из массива загрузчиков и показывать его на экране. Для того, чтобы проследить какое конкретно изображение показывается на экране в данный момент, нам нужно создать переменную - счетчик. И опять в верху нашего кода объявим эту переменную. Начальное значение - ноль, обращается к первому изображению в массиве загрузчиков: CODE:
Теперь мы можем создать функцию nextImage(), которая будет использовать счетчик my_playback_counter, чтобы извлекать нужный загрузчик и добавлять его в дисплей лист. Напишите в самом низу нашего с вами кода: CODE:
Мы можем вызывать эту функцию из функции startShow(), чтобы первое изображение отображалось, когда слайдшоу начинает работу. CODE:
Теперь мы можем первый раз испытать наш клип (Window>Test Movie или Ctrl+Enter), чтобы увидеть первое изображение, отображающиеся на экране.
Нам нужно, чтобы наша функция nextImage() распологала изображение в центре экрана. Мы можем добиться этого, используя простую формулу, которая использует ширину изображения и ширину экрана, чтобы определить правильное место, чтобы позиционировать изображение в центре. Та же самая концепция примяется и к ветикальной позиции изображения: CODE:
Мы можем сделать чтобы наше изображение постепенно проявлялось, вместо обычного резкого появления, используя класс анимации Tween Class. Естественно, перед тем как использовать этот класс, мы должны импортировать необходимые для этого классы, используя команду import в самом начале нашего кода: CODE:
Теперь, когда мы сделали это, мы можем использовать простую анимацию, чтобы анимировать значение прозрачности нашего изображения, вот таким образом: CODE:
Теперь вы можете проверить ваш клип отять, чтобы увидеть что первое изображение появляется плавно, используя анимацию. Этого метода должно быть достаточно для нас, чтобы загрузить любое изображение, нам просто нужно повторять его, используя класс Timer Class. Используем таймерДля того, чтобы наше слайдшоу работало, мы должны использовать класс Timer Class, чтобы код исполнялся циклически повторяясь. Наш таймер будет ответственнен за обновление нашего счетчика my_playback_counter и затем вызывал функцию nextImage() чтобы отобразить следующее изображение. Мы должны иметь возможность использвать наш таймер на протяжении всей работы нашего слайдшоу, поэтому нам нужно объявить его переменную как глобальную в верху нашего с вами кода: CODE:
Теперь мы можем сконфигурировать наш таймер из функции startShow(). CODE:
Наш таймер должен испонять свой код через отдельный слушатель событий, который мы зарегистрируем вместе с ним. CODE:
Ну, и , конечно, мы должны запустить наш таймер, используя метод .start(): CODE:
Наш таймер должен включиться, когда мы будем тестировать клип, но мы еще не написали код, который таймер будет исполнять циклически. Он будет работать в функции timerListener(). Создадим эту функцию в самом низу нашего с вами кода: CODE:
Функция timerListener() будет иметь две основные задачи, первая - увеличивать значение переменной my_playback_counter на 1, так, чтобы слайдшоу двигалось вперед, и затем вызывать функцию nextImage(), чтобы показать следующее изображение: CODE:
Вы можете протестировать ваш клип (Control>Test Movie) и теперь увидеть что слайдшоу работает, показывая изображения с интервалом в 1 секунду. Конечно вы еще можете заметить, что шоу останавливается после показа последней картинки и появляется сообщение об ошибках. Это происходит потому, что значение счетчика показов превышает количество изображений в слайдшоу. Чтобы исправить это положение дел, мы можем использовать условие, чтобы сбрасывать счетчик на ноль, когда он достигнет максимального значения равного количеству изображений в слайдшоу: CODE:
Ну, вот, теперь все должно работать правильно. Проверьте свой клип, теперь он должен работать циклично. Анимация должна работать плавно, если вы используете изображения одного размера, но если у вас картинки разных размеров, то она может выглядеть не столь хорошо, но с этим мы разберемся позже. Следующим шагом в нашем проекте будет являться добавление текстовых описаний - лейблов к каждому изображению. Этот процесс очень похож на процесс показа изображений, нам нужно создать множество экземпляров класс TextField Class для каждого лейбла, затем мы должны добавить их в отдельный массив, создать отдельный контейнер, чтобы отображать их, и затем использовать функцию, идентичную nextImage(), чтобы отображать их на экране. Создание текстовых полей, извлечение лейблов и добавление их в массив.Мы собираемся создать отдельные текстовые поля для каждого лейбла, присвоить текст этого текстового поля лейблу и затем добавить его в отдельный массив, чтобы иметь возможность свободного доступа к нему. Мы можем сделать это используя нашу уже существующую функцию loadImages() так как эта функция обрабатывает элементы XML, используя цикл. Начнем с создания нового экземпляра текстового поля под именем my_label: CODE:
Вы можете теперь извлечь лейбл каждого из наших изображений, используя оператор @ извлечь значение атрибута title и прямо установить его как значение для свойства .text текстового поля: CODE:
Теперь нам нужно так сконфигурировать наше текстовое поле, чтобы оно вмещало лейбл любого размера, используя свойство .autoSize автоматического расширения: CODE:
Наш финальный шаг - добавить наше текстовое поле в специальный массив для лейблов. Нам нужен этот массив, чтобы в дальнейшем обращаться к нашим лейблам. Создадим этот массив вверху нашего кода, чтобы он оставался в постоянном доступе: CODE:
Мы можем теперь с легкостью добавить наши лейблы в этот массив, используя метод .push(): CODE:
Теперь мы должны создать контейнеры для лейблов. Создание контейнеров для лейбловНам нужен отдельный контейнер для наших лейблов так, чтобы иметь организованную структуру для наших визуальных объектов. У нас есть один для изображений и мы нуждаемся еще в одном для наших текстовых лейблов. Просто объявляем его вверху нашего кода: CODE:
Мы можем добавить его в дисплей лист, используя метод .addChild() в нашей функции startShow(): CODE:
Показываем лейблы на экранеОтображение лейблов на экране будет сделано точно таким же способом как и в случае с изображениями. CODE:
Теперь наши текстовые поля должны отобразиться на экране, но расположены они не правильно. Их горизонтальная координата должна быть точно такой же как и у изображений, а ветикальная - по нижнему краю изображения. Вычисляется это следующим образом: CODE:
Мы так же можем добавить анимацию прозрачности к текстовым лейблам как мы делали с изображениями, используя Tween Class: CODE:
Теперь вы можете протестировать ваш клип и увидеть, что ваши лейблы плавно появляются в правильной позиции. Правда, вы заметите большую проблему с ними, так как предыдущие текстовые поля не убираются, когда появляются новые, напрочь портя всю картину. Если вы используете изображения разных размеров, вы так же можете заметить что они остаются фоном, когда другие появляются. Мы решим эту проблему создав новую функцию hidePrev(), чтобы устранить это досадное недоразумение. Создание функции hidePrev()Проблема с нашими размножившимися текстовыми лейблами и картинками может быть устранена путем создания функции, прячущей с экрана лейбл и картинку перед тем как показать следующие. Мы должны вызвать эту функцию перед тем как обновим счетчик my_current_playback или даже обратимся к функции nextImage(). Мы хотим убрать первый лейбл и изображение, отображаемое на экране, так что мы можем обратиться к ним, используя их позицию в дисплей листах. Мы можем просто использовать Tween Class, чтобы плавно растворить их, анимируя прозрачность. Вы можете написать следующий код внизу нашего существующего кода, чтобы сделать это: CODE:
Мы можем теперь вызвать эту функцию прямо из функции слушателя событий нашего таймера: CODE:
При тестировании этого кода пропадет только первый слайд, но ничего больше, так происходит потому что все остальные картинки и лейблы расположены после индекса 0 в их дисплей листах до тех пор, пока первые остаются там. Нам нужно убрать изоьражение и лейбл из их дисплей листов после того как они растворятся. Чтобы сделать это нам нужно зарегистрировать одну из наших анимаций со слушателем событий. Нам нужно создать глобальную переменную для нашей анимации в начале нашего кода: CODE:
Теперь мы можем добавить слушатель событий к нашей функции hidePrev(). Обе наши анимации картинки и лейбла занимают одинаковое время, так что по этой причине мы можем убрать их обе, используя один и тот же слушатель, вместо отдельного для каждой. CODE:
Теперь мы можем создать функцию onFadeOut() чтобы убрать child с позиции 0 для каждого контейнера: CODE:
Теперь вы можете протестировать ваше слайдшоу, чтобы увидеть что работает оно замечательно. Добавляем простой прелоадерВ зависимости от количества картинок в вашем слайдшоу, закачивание их может занять продолжительное время. Чтобы информировать пользователей что клип не повис и что он в данный момент успешно закачивается, мы можем добавить простой текст, ообъясняющий это. Первый шаг в создании этого прелоадера состоит в создании переменной, в которой будет помещаться текстовое поле. Создадим эту переменную в самом верху нашего кода, так как она должна быть глобальной, для возможности постоянного доступа к ней: CODE:
Теперь, внутри нашей функции loadImages() мы собираемся создать текстовое поле, чтобы оно показывало слово "Loading", правильно позиционировать его и затем добавить в дисплей лист. Заметьте что код должен быть расположен вне цикла, но внутри тела функции: CODE:
Нам необходимо, чтобы это текстовое поле было убрано из дисплей листа, когда слайдшоу начнет работать: CODE:
Ну, вот, теперь у нас есть простой текстовый прелоадер, который будет демонстрироваться пока не закачаются все изображения. Оптимизируем кодНаше слайдшоу должно работать замечательно в большинстве обстоятельств, однако, практика требует от нас оптимизировать код и очистить его от лишнего, чтобы наш клип работал без риска каких либо проблем с памятью. Мы можем сделать это отменяя регистрацию событий и убирая объекты которые больше не нужны. Мы будем делать это шаг за шагом. Начнем с нашей первой функции слушателя событий processXML(). Раз эта функция уже выполнена, то больше нет необходимости для нее быть зарегистрированной нашим экземпляром URLLoder, а так же нет никакой необходимости в самом экземпляре URLLoader, так как все данные, что нам нужны уже помещены в разных переменных. Мы можем отменить регистрацию события, используя метод removeEventListener() и мы можем убрать экземпляр установив его значение в null: CODE:
Перейдем к процессу загрузки изображений, функция onComplete() тоже больше не нужна, так как все изображения уже закачаны. CODE:
Ну и в конце, по причине непредсказуемого процесса очистки от мусора в AS3, анимации класса Tween Class, которые не связаны, используя какую-нибудь постоянную ссылку, могут быть уничтожены в случайном порядке в некоторых браузерах. Чтобы быть уверенными что этого не случится с нашими анимациями, мы можем использовать массив чтобы сохранять ссылки на наши анимации. Начнем с того, что создадим новый массив вверху нашего кода: CODE:
Теперь мы собираемся поместить все наши анимации в этом массиве. Начнем с обновления функции nextImage() вот таким образом: CODE:
Ну и финальный шаг - обновим функцию hidePrev() таким же точно образом: CODE:
Ну и теперь мы можем также убрать текстовое поле прелоадеракогда шоу начнется, вместо того , чтобы просто убрать его из дисплей листа. Мы можем сделать это, установив значение этой переменно на null: CODE:
Ну, вот, теперь у нас сполностью функциональное и оптимизированное слайдшоу. Перевод с английского языка: Солнцев А. Оригинал статьи на английском языке: www.republicofcode.com Комментарии ВКонтакте |